/*
 * Copyright 2008 Neil Bacon
 * Distributed under the terms of the Mozilla Public License version 1.1
 * or the GNU General Public License version 3.
 */

package nb.xadd.node.impl;

import nb.util.Utils;
import nb.xadd.node.Node;
import nb.xadd.operator.BinaryOperator;

public class BooleanDecisionNode extends AbstractDecisionNode {
    private final int booleanVarIndex;
    private final int hashCode;

    protected BooleanDecisionNode(int booleanVarIndex, Node trueChild, Node falseChild) {
        super(trueChild, falseChild);
        this.booleanVarIndex = booleanVarIndex;
        hashCode = calcHashCode();
    }

    @Override
    public int hashCode() {
        return hashCode;
    }

    protected int calcHashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + super.calcHashCode();
        result = prime * result + booleanVarIndex;
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (!super.equals(obj))
            return false;
        BooleanDecisionNode other = (BooleanDecisionNode) obj;
        return booleanVarIndex == other.booleanVarIndex;
    }

    @Override
    public Ordering getOrdering() {
        return Ordering.BOOLEAN;
    }

    public int getBooleanVarIndex() {
        return booleanVarIndex;
    }

    //	@Override
    //	public boolean isTrue(DataModel model) {
    //		return model.getBoolean(booleanVarIndex);
    //	}
    //
    @Override
    public int compareTo(Node other) {
        int i = super.compareTo(other);
        if (i != 0) {
            return i;
        }
        BooleanDecisionNode dn = (BooleanDecisionNode) other;
        return booleanVarIndex - dn.booleanVarIndex;
    }

    @Override
    public Node apply(BinaryOperator binaryOperator, Node node) {
        return node.applyBooleanDecision(binaryOperator, this);
    }

    @Override
    public Node applyConstantValue(BinaryOperator binaryOperator, ConstantValueNode node) {
        return binaryOperator.executeConstantBooleanDecision(node, this);
    }

    @Override
    public Node applyLinearValue(BinaryOperator binaryOperator, LinearValueNode node) {
        return binaryOperator.executeLinearBooleanDecision(node, this);
    }

    @Override
    public Node applyPolynomialValue(BinaryOperator binaryOperator, PolynomialValueNode node) {
        return binaryOperator.executePolynomialBooleanDecision(node, this);
    }

    @Override
    public Node applyBooleanDecision(BinaryOperator binaryOperator, BooleanDecisionNode node) {
        return binaryOperator.executeBooleanDecisionBooleanDecision(node, this);
    }

    @Override
    public Node applyRealEqualDecision(BinaryOperator binaryOperator, RealEqualDecisionNode node) {
        return binaryOperator.executeBooleanDecisionRealEqualDecision(this, node);
    }

    @Override
    public Node applyRealGreaterOrEqualDecision(BinaryOperator binaryOperator, RealGreaterOrEqualDecisionNode node) {
        return binaryOperator.executeBooleanDecisionRealGreaterOrEqualDecision(this, node);
    }

    @Override
    public void appendTo(int depth, StringBuilder buf) {
        Utils.appendIndent(depth, buf);
        buf.append("id = ").append(getId()).append(", b").append(booleanVarIndex).append(" ?\n");
        super.appendTo(depth, buf);
    }

    @Override
    public String description() {
        return "id = " + getId() + ", b" + booleanVarIndex + " ?";
    }

}
